home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-08-22 | 64.4 KB | 2,560 lines |
- This is a new archive version of TRN at patchlevel 3.
- The original posting took up Volume23, issues 60 to 73, with
- various problems. These files replace those issues.
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: bits.h init.c mthreads.1 ngdata.c ngstuff.c term.h util.c
- # Wrapped by rsalz@litchi.bbn.com on Fri Aug 23 16:39:01 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 11 (of 14)."'
- if test -f 'bits.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'bits.h'\"
- else
- echo shar: Extracting \"'bits.h'\" \(2440 characters\)
- sed "s/^X//" >'bits.h' <<'END_OF_FILE'
- X/* $Header: bits.h,v 4.3.3.2 91/01/16 02:29:50 davison Trn $
- X *
- X * $Log: bits.h,v $
- X * Revision 4.3.3.2 91/01/16 02:29:50 davison
- X * Added optional prototyping.
- X *
- X * Revision 4.3.3.1 90/06/20 22:36:35 davison
- X * Initial Trn Release
- X *
- X * Revision 4.3.2.1 90/11/22 15:46:42 sob
- X * Made changes to make pickly preprocessors happier.
- X *
- X * Revision 4.3.1.2 86/11/03 09:49:58 lwall
- X * Added firstbit variable.
- X *
- X * Revision 4.3.1.1 85/05/10 11:31:52 lwall
- X * Branch for patches.
- X *
- X * Revision 4.3 85/05/01 11:36:39 lwall
- X * Baseline for release with 4.3bsd.
- X *
- X */
- X
- XEXT char *ctlarea INIT(Nullch); /* one bit for each article in current newsgroup */
- X /* with the following interpretation: */
- X /* 0 => unread */
- X /* 1 => read */
- X
- X/* if subscripting is faster than shifting on your machine, define this */
- X#undef USESUBSCRIPT
- X#ifdef USESUBSCRIPT
- XEXT char powerof2[] INIT({1,2,4,8,16,32,64,128});
- X#define pow2(x) powerof2[x]
- X#else
- X#define pow2(x) (1 << (x))
- X#endif
- X
- X#ifdef lint
- XEXT bool nonesuch INIT(FALSE);
- X#define ctl_set(a)
- X#define ctl_clear(a)
- X#define ctl_read(a) nonesuch
- X#define was_read(a) nonesuch
- X#else
- X#define ctl_set(a) (ctlarea[(OFFSET(a)) / BITSPERBYTE] |= pow2((OFFSET(a)) % BITSPERBYTE))
- X#define ctl_clear(a) (ctlarea[(OFFSET(a)) / BITSPERBYTE] &= ~pow2((OFFSET(a)) % BITSPERBYTE))
- X#define ctl_read(a) ((ctlarea[(OFFSET(a)) / BITSPERBYTE] & pow2((OFFSET(a)) % BITSPERBYTE)) != 0)
- X
- X#define was_read(a) ((a)<firstbit || ctl_read(a))
- X#endif /* lint */
- X
- XEXT ART_NUM absfirst INIT(0); /* 1st real article in current newsgroup */
- XEXT ART_NUM firstart INIT(0); /* minimum unread article number in newsgroup */
- XEXT ART_NUM firstbit INIT(0); /* minimum valid bit, usually == firstart */
- XEXT ART_NUM lastart INIT(0); /* maximum article number in newsgroup */
- X
- X#ifdef DELAYMARK
- XEXT FILE *dmfp INIT(Nullfp);
- XEXT char *dmname INIT(Nullch);
- XEXT int dmcount INIT(0);
- X#endif
- X
- Xvoid bits_init ANSI((void));
- Xvoid checkpoint_rc ANSI((void));
- Xvoid restore_ng ANSI((void));
- Xvoid onemore ANSI((ART_NUM));
- Xvoid oneless ANSI((ART_NUM));
- Xvoid unmark_as_read ANSI((void));
- X#ifdef USETHREADS
- Xvoid set_read ANSI((ART_NUM,int));
- Xvoid set_unread ANSI((ART_NUM,int));
- X#endif
- Xvoid delay_unmark ANSI((ART_NUM));
- Xvoid mark_as_read ANSI((void));
- Xvoid check_first ANSI((ART_NUM));
- X#ifdef DELAYMARK
- X void yankback ANSI((void));
- X#endif
- Xint chase_xrefs ANSI((ART_NUM,int));
- Xint initctl ANSI((void));
- Xvoid grow_ctl ANSI((ART_NUM));
- END_OF_FILE
- if test 2440 -ne `wc -c <'bits.h'`; then
- echo shar: \"'bits.h'\" unpacked with wrong size!
- fi
- # end of 'bits.h'
- fi
- if test -f 'init.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'init.c'\"
- else
- echo shar: Extracting \"'init.c'\" \(8905 characters\)
- sed "s/^X//" >'init.c' <<'END_OF_FILE'
- X/* $Header: init.c,v 4.3.3.2 91/01/16 02:43:39 davison Trn $
- X *
- X * $Log: init.c,v $
- X * Revision 4.3.3.2 91/01/16 02:43:39 davison
- X * Integrated rn patches 48-54. Twiddled 'rn' to 'trn'.
- X *
- X * Revision 4.3.3.1 90/06/20 22:37:39 davison
- X * Initial Trn Release
- X *
- X * Revision 4.3.2.8 90/11/22 13:51:39 sob
- X * Removed some cruft trailing the #endif directive to make more compilers
- X * happy.
- X *
- X * Revision 4.3.2.7 90/10/30 22:42:23 sob
- X * Used fileno() instead of _file to increase portability.
- X *
- X * Revision 4.3.2.6 90/05/08 22:05:55 sob
- X * Added quick startup (-q) flag.
- X *
- X * Revision 4.3.2.5 90/05/04 23:10:01 sob
- X * Fix for exiting "second" rn such that tty will be left in correct state.
- X * Provided by glenn@mathcs.emory.edu
- X *
- X * Revision 4.3.2.4 90/03/22 23:04:32 sob
- X * Fixes provided by Wayne Davison <drivax!davison>
- X *
- X * Revision 4.3.2.3 90/03/17 21:34:04 sob
- X * Cleaned up a bit.
- X *
- X * Revision 4.3.2.2 89/11/08 01:17:48 sob
- X * Added changes to insure that this will compile for RN or RRN with no
- X * changes to the source code.
- X *
- X * Revision 4.3.2.1 89/11/06 00:39:14 sob
- X * Added RRN support from NNTP 1.5
- X *
- X * Revision 4.3.1.4 86/09/05 14:24:02 lwall
- X * Removed net.announce dependency.
- X *
- X * Revision 4.3.1.3 85/07/23 18:08:36 lwall
- X * Fixed up NOLINEBUF option to work.
- X *
- X * Revision 4.3.1.2 85/05/21 14:22:46 lwall
- X * Sped up "rn -c" by avoiding unnecessary initialization.
- X *
- X * Revision 4.3.1.1 85/05/10 11:33:39 lwall
- X * Branch for patches.
- X *
- X * Revision 4.3 85/05/01 16:16:13 lwall
- X * Baseline for release with 4.3bsd.
- X *
- X */
- X
- X#include "EXTERN.h"
- X#include "common.h"
- X#include "util.h"
- X#include "final.h"
- X#include "term.h"
- X#include "last.h"
- X#include "rn.h"
- X#include "rcstuff.h"
- X#include "ngdata.h"
- X#include "only.h"
- X#include "intrp.h"
- X#include "addng.h"
- X#include "sw.h"
- X#include "art.h"
- X#include "artsrch.h"
- X#include "artio.h"
- X#include "backpage.h"
- X#include "bits.h"
- X#include "cheat.h"
- X#include "head.h"
- X#include "help.h"
- X#include "kfile.h"
- X#include "ngsrch.h"
- X#include "ngstuff.h"
- X#include "rcln.h"
- X#include "respond.h"
- X#ifdef SERVER
- X#include "server.h"
- X#endif
- X#ifdef USETHREADS
- X#include "rthreads.h"
- X#endif
- X#include "ng.h"
- X#include "INTERN.h"
- X#include "init.h"
- X
- Xbool
- Xinitialize(argc,argv)
- Xint argc;
- Xchar *argv[];
- X{
- X char *tcbuf;
- X register bool foundany = FALSE;
- X long time();
- X#ifdef SERVER
- X char *server;
- X int response;
- X#endif
- X#ifdef NOLINEBUF
- X static char std_out_buf[BUFSIZ]; /* must be static or malloced */
- X
- X setbuf(stdout, std_out_buf);
- X#endif
- X
- X tcbuf = safemalloc(1024); /* make temp buffer for termcap and */
- X /* other initialization stuff */
- X
- X /* init terminal */
- X
- X term_init(); /* must precede sw_init() so that */
- X /* ospeed is set for baud-rate */
- X /* switches. Actually terminal */
- X /* mode setting is in term_set() */
- X
- X /* we have to know rnlib to look up global switches in %X/INIT */
- X
- X lib = savestr(filexp(LIB));
- X rnlib = savestr(filexp(RNLIB));
- X
- X /* decode switches */
- X
- X sw_init(argc,argv,&tcbuf); /* must not do % interps! */
- X /* (but may mung environment) */
- X
- X /* init signals, status flags */
- X
- X final_init();
- X
- X /* start up file expansion and the % interpreter */
- X
- X intrp_init(tcbuf);
- X
- X /* now make sure we have a current working directory */
- X
- X if (!checkflag)
- X cwd_check();
- X
- X /* now that we know where to save things, cd to news directory */
- X
- X if (chdir(spool)) {
- X printf(nocd,spool) FLUSH;
- X finalize(1);
- X }
- X
- X /* if we aren't just checking, turn off echo */
- X
- X if (!checkflag)
- X term_set(tcbuf);
- X
- X /* get info on last rn run, if any */
- X
- X if (!checkflag)
- X last_init(tcbuf);
- X
- X free(tcbuf); /* recover 1024 bytes */
- X
- X /* make sure we are the sole possessors of .newsrc */
- X
- X if (!checkflag)
- X lock_check();
- X
- X /* check for news news */
- X
- X if (!checkflag)
- X newsnews_check();
- X
- X#ifdef SERVER
- X
- X /* open connection to server if appropriate */
- X
- X server = getserverbyfile(SERVER_FILE);
- X if (server == NULL) {
- X fprintf(stderr, "Can't get the name of the news server from %s\n",
- X SERVER_FILE);
- X fprintf(stderr,
- X "Either fix this file, or put NNTPSERVER in your environment.\n");
- X finalize(1);
- X }
- X
- X response = server_init(server);
- X if (response < 0) {
- X fprintf(stderr,
- X "Couldn't connect to %s news server, try again later.\n",
- X server);
- X finalize(1);
- X }
- X
- X if (handle_server_response(response, server) < 0)
- X finalize(1);
- X
- X#endif
- X
- X /* open active file, etc. */
- X
- X ngdata_init();
- X
- X /* now read in the .newsrc file */
- X
- X foundany = rcstuff_init();
- X
- X /* it looks like we will actually read something, so init everything */
- X
- X addng_init();
- X art_init();
- X artio_init();
- X artsrch_init();
- X backpage_init();
- X bits_init();
- X cheat_init();
- X head_init();
- X help_init();
- X kfile_init();
- X ng_init();
- X ngsrch_init();
- X ngstuff_init();
- X only_init();
- X rcln_init();
- X respond_init();
- X rn_init();
- X search_init();
- X#ifdef USETHREADS
- X thread_init();
- X#endif
- X util_init();
- X
- X#ifdef FINDNEWNG
- X/* fstat(actfp->_file,&filestat); ... does not work on Apollos */
- X fstat(fileno(actfp),&filestat); /* did active file grow? */
- X /*
- X * Skip this check if the -q flag was given.
- X */
- X
- X if (!quickstart && filestat.st_size != lastactsiz) {
- X long actsiz = filestat.st_size; /* remember new size */
- X NG_NUM oldnext = nextrcline; /* remember # lines in newsrc */
- X#ifdef FASTNEW
- X bool munged = writesoft || !lastactsiz;
- X /* bad soft ptrs -> edited active */
- X#else
- X bool munged = TRUE; /* just assume .newsrc munged */
- X#endif
- X
- X#ifdef VERBOSE
- X IF(verbose)
- X fputs("\nChecking active list for new newsgroups...\n",stdout)
- X FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X fputs("\nNew newsgroups:\n",stdout) FLUSH;
- X#endif
- X#ifdef FASTNEW
- X if (!munged) { /* maybe just do tail of file? */
- X fseek(actfp,lastactsiz-NL_SIZE,0);
- X fgets(buf,LBUFLEN,actfp);
- X munged = (*buf != '\n');
- X if (!munged)
- X munged = newlist(munged,FALSE);
- X }
- X#endif
- X if (munged) { /* must we scan entire file? */
- X fseek(actfp,0L,0); /* rewind active file */
- X newlist(munged,FALSE); /* sure hope they use hashing... */
- X }
- X lastactsiz = actsiz; /* remember for .rnlast */
- X if (nextrcline != oldnext) { /* did we add any new groups? */
- X foundany = TRUE; /* let main() know */
- X starthere = 0; /* and start ng scan from the top */
- X }
- X }
- X#endif
- X time(&lasttime); /* remember when we inited-- */
- X /* ends up back in .rnlast */
- X writelast(); /* in fact, put it there now */
- X
- X#ifdef FINDNEWNG
- X# ifdef ONLY
- X if (maxngtodo) /* patterns on command line? */
- X foundany |= scanactive();
- X# endif
- X#endif
- X
- X return foundany;
- X}
- X
- X/* make sure there is no rn out there already */
- X
- Xvoid
- Xlock_check()
- X{
- X lockname = savestr(filexp(LOCKNAME));
- X if (!checkflag) {
- X tmpfp = fopen(lockname,"r");
- X if (tmpfp != Nullfp) {
- X int processnum;
- X
- X fgets(buf,LBUFLEN,tmpfp);
- X fclose(tmpfp);
- X processnum = atoi(buf);
- X#ifdef VERBOSE
- X IF(verbose)
- X printf("You seem to have left a trn running, process %d.\n",
- X processnum) FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X printf("Trn left running, #%d.\n", processnum) FLUSH;
- X#endif
- X if (kill(processnum, SIGEMT)) {
- X /* does process not exist? */
- X /* (rn ignores SIGEMT) */
- X sleep(2);
- X#ifdef VERBOSE
- X IF(verbose)
- X fputs("\n\
- XThat process does not seem to exist anymore. The count of read articles\n\
- Xmay be incorrect in the last newsgroup accessed by that other (defunct)\n\
- Xprocess.\n\n",stdout) FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X fputs("\nProcess crashed.\n",stdout) FLUSH;
- X#endif
- X if (*lastngname) {
- X#ifdef VERBOSE
- X IF(verbose)
- X printf("(The last newsgroup accessed was %s.)\n\n",
- X lastngname) FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X printf("(In %s.)\n\n",lastngname) FLUSH;
- X#endif
- X }
- X get_anything();
- X putchar('\n') FLUSH;
- X }
- X else {
- X#ifdef VERBOSE
- X IF(verbose)
- X fputs("\n\
- XYou may not have two copies of [t]rn running simultaneously. Goodbye.\n\
- X",stdout) FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X fputs("\nCan't start another.\n",stdout) FLUSH;
- X#endif
- X if (bizarre)
- X resetty();
- X exit(0);
- X }
- X }
- X tmpfp = fopen(lockname,"w");
- X if (tmpfp == Nullfp) {
- X printf(cantcreate,lockname) FLUSH;
- X sig_catcher(0);
- X }
- X fprintf(tmpfp,"%d\n",getpid());
- X fclose(tmpfp);
- X }
- X}
- X
- Xvoid
- Xnewsnews_check()
- X{
- X char *newsnewsname = filexp(NEWSNEWSNAME);
- X
- X if ((tmpfp = fopen(newsnewsname,"r")) != Nullfp) {
- X/* fstat(tmpfp->_file,&filestat); .... does not work on Apollos */
- X fstat(fileno(tmpfp),&filestat);
- X if (filestat.st_mtime > lasttime) {
- X while (fgets(buf,sizeof(buf),tmpfp) != Nullch)
- X fputs(buf,stdout) FLUSH;
- X get_anything();
- X putchar('\n') FLUSH;
- X }
- X fclose(tmpfp);
- X }
- X}
- END_OF_FILE
- if test 8905 -ne `wc -c <'init.c'`; then
- echo shar: \"'init.c'\" unpacked with wrong size!
- fi
- # end of 'init.c'
- fi
- if test -f 'mthreads.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mthreads.1'\"
- else
- echo shar: Extracting \"'mthreads.1'\" \(9578 characters\)
- sed "s/^X//" >'mthreads.1' <<'END_OF_FILE'
- X''' $Header: mthreads.1,v 4.3.3.3 91/01/18 19:27:39 davison Trn $
- X'''
- X''' $Log: mthreads.1,v $
- X''' Revision 4.3.3.3 91/01/18 19:27:39 davison
- X''' Added commands -s and -z.
- X'''
- X''' Revision 4.3.3.2 90/08/20 16:42:32 davison
- X''' Document new command-line interface.
- X'''
- X''' Revision 4.3.3.1 90/07/21 20:03:37 davison
- X''' Initial Trn Release
- X'''
- X'''
- X.de Sh
- X.br
- X.ne 5
- X.PP
- X\fB\\$1\fR
- X.PP
- X..
- X.de Sp
- X.if t .sp .5v
- X.if n .sp
- X..
- X.de Ip
- X.br
- X.ie \\n.$>=3 .ne \\$3
- X.el .ne 3
- X.IP "\\$1" \\$2
- X..
- X'''
- X''' Set up \*(-- to give an unbreakable dash;
- X''' string Tr holds user defined translation string.
- X''' Bell System Logo is used as a dummy character.
- X'''
- X.tr \(bs-|\(bv\*(Tr
- X.ie n \{\
- X.ds -- \(bs-
- X.if (\n(.H=4u)&(1m=24u) .ds -- \(bs\h'-12u'\(bs\h'-12u'-\" diablo 10 pitch
- X.if (\n(.H=4u)&(1m=20u) .ds -- \(bs\h'-12u'\(bs\h'-8u'-\" diablo 12 pitch
- X.ds L" ""
- X.ds R" ""
- X.ds L' '
- X.ds R' '
- X'br\}
- X.el\{\
- X.ds -- \(em\|
- X.tr \*(Tr
- X.ds L" ``
- X.ds R" ''
- X.ds L' `
- X.ds R' '
- X'br\}
- X.TH MTHREADS 1 LOCAL
- X.UC 6
- X.SH NAME
- Xmthreads - threaded database manager for trn
- X.SH SYNOPSIS
- X.B mthreads [-d[MM]] [-e[HHMM]] [-aDfknv] [hierarchy_list]
- X.SH DESCRIPTION
- X.I Mthreads
- Xmanages the thread files that are used by the
- X.IR trn (1)
- Xnewsreader.
- X\*(L"Thread files\*(R" are used to store information about the news
- Xarticles and how they are all related to one another.
- X.PP
- X.I Mthreads
- Xneeds to be run
- Xperiodically \*(-- either in single-pass mode out of cron,
- Xor in daemon mode out of the boot script \*(-- to update the thread
- Xinformation whenever new news is received.
- XA site that gets its news feed during the night and doesn't need local
- Xpostings processed throughout the day can run
- X.I mthreads
- Xin single-pass mode once a day.
- XIf more processing is needed, either run
- X.I mthreads
- Xmore often or run it in daemon mode.
- XIn daemon mode, a background process is forked off that wakes up every 10
- Xminutes (by default) to check if the active file has been updated.
- X.SH INSTALLATION
- X.I Mthreads
- Xin installed in the RNLIB directory chosen during configuration.
- XWhen it is run for the first time, it will automatically create a file called
- X.I active2
- Xin the same directory.
- XThis file is essentially a copy of the active file that keeps the newsgroup
- Xtotals from the last run in one place.
- XIt is also used to choose which groups are to be processed into thread files.
- XAll groups start out as \*(L"unthreaded\*(R" unless they are turned on with
- Xa command like:
- X.IP
- Xmthreads all
- X.PP
- Xwhich would create thread file for all the groups.
- XFor testing purposes it is a good idea to start out small with a command
- Xlike:
- X.IP
- Xmthreads news
- X.PP
- Xwhich would thread only the news hierarchy.
- XThread processing can be turned on or off for individual groups or entire
- Xhierarchies by specifying the groups in a syntax very similar to that used
- Xin the sys file.
- XFor example, to turn on all of soc and talk except for talk.politics, and
- Xto turn off news.lists, use the following command once:
- X.IP
- Xmthreads soc,talk,!talk.politics,!news.lists
- X.PP
- XIf mthreads complains that another mthreads process is already running,
- Xit can be killed with the command:
- X.IP
- Xmthreads -k
- X.PP
- Xand then repeat the prior command after giving it a little time to die.
- X.PP
- XOnce all the desired groups are turned on, it is not necessary to
- Xspecify a hierarchy list for the normal functioning of mthreads.
- XIt can be used, however, to customize which new groups get turned on
- Xas they are created.
- X.SH LOGGING
- XAs mthreads executes, some status information (including error messages)
- Xis placed in
- Xthe file mt.log in the RNLIB directory.
- XThis file will grow without bounds, and should be scanned periodically for
- Xerrors, and trimmed in size when it grows too large.
- XSee the shell script
- X.I mt.check
- Xfor an mt.log maintainer that will send mail if it finds database errors.
- X.SH OPTIONS
- X.TP 5
- X.B \-a
- Xis used to automatically turn on thread processing for new news groups as
- Xthey are created.
- XThe default is to leave new groups unthreaded.
- X.TP 5
- X.B \-D
- Xspecifies a debugging mode where only the groups mentioned on the
- Xcommand-line are processed \*(-- all other groups are left unchanged.
- XIt also outputs each group's name into the log file before it is processed.
- X.TP 5
- X.B \-d
- Xis used to specify the daemon mode, where
- X.I mthreads
- Xforks a background task that periodically wakes up and checks for an updated
- Xactive file.
- XThe number of minutes to wait after the completion of the last pass can
- Xbe specified after the '-d' option (e.g. -d20), otherwise it will default to
- X10 minutes.
- X.TP 5
- X.B \-e
- Xtells
- X.I mthreads
- Xto run an enhanced expiration check on the database.
- XWithout this option, only articles below the minimum field in the active
- Xfile are expired.
- XWith this option, all unexpired articles in the database are stat()'ed to
- Xsee if they actually exist.
- XIn single-pass mode the
- X.B -e
- Xoption always affects the current pass \*(-- use it
- Xonce a day after expire has run.
- XIn daemon mode, the
- X.B -e
- Xoption will cause one pass a day to be the enhanced expire pass.
- XBy default, this is the first time mthreads wakes up after 12:30 am.
- XIf a different time is desired, it can be specified in the form HHMM
- X(e.g. -e2359).
- X.TP 5
- X.B -f
- Xis used to force
- X.I mthreads
- Xto open each and every thread file to see which ones really need to be
- Xupdated, not just the ones that differ in the active/active2 comparison.
- XIt will also remove any extraneous thread files from unthreaded groups
- X(which should only occur if you manually change the active2 file).
- XThis option should only be used when manipulating the thread files in
- Xunorthodox ways.
- X.TP 5
- X.B -k
- Xcan be used to terminate the currently running mthreads, just as if it
- Xhad received a terminate signal.
- XWhen this option is specified, no other activity is performed.
- X.TP 5
- X.B -n
- Xtells
- X.I mthreads
- Xthat no actual processing of thread files is to be performed.
- XThis can be used to just adjust which groups are to be processed, without
- Xactually doing any of the processing right away.
- X.TP 5
- X.B -s
- Xtells mthreads to sleep one second before processing each article.
- XThis is useful if your NNTP server cannot handle mthreads running at
- Xfull speed.
- XFor each additional
- X.B -s
- Xspecified, mthreads sleeps an additional second.
- X.TP 5
- X.B -v
- Xselects additional levels of verbosity in the log file.
- XThe default (without -v) is to log mthread's startup, the totals for each
- Xpass, the inclusion of the enhanced expire option, and major database errors.
- XAdd one
- X.B -v
- Xto get extra reference line problems logged into the file.
- XAdd a second and a third for even more (useless?) information.
- XA fourth will cause mthreads to output each group's name into the log file
- Xbefore it is processed.
- X.TP 5
- X.B -z
- Xtells mthreads to 'zap' any thread file it believes to be corrupt.
- XThis will allow the file to be regenerated from scratch on the next pass.
- X.TP 5
- X.B hierarchy_list
- XThe hierarchy list is used to turn thread processing on or off for the listed
- Xgroups.
- XThe groups are specified in a manner very similar to the news software's
- Xsys file: \*(L"news\*(R" matches all groups in news; \*(L"!news\*(R" excludes
- Xall groups in news; \*(L"comp.all.ibm.pc,!comp.all.ibm.pc.all\*(L" matches both
- Xcomp.sys.ibm.pc and comp.binaries.ibm.pc, but not comp.binaries.ibm.pc.d.
- X.Sp
- XThe hierarchy_list is also used in conjunction with the debug flag to only
- Xprocess one or more groups for testing purposes.
- X.SH OUTPUT
- XWhen
- X.I mthreads
- Xis run in single-pass mode it generates a stream a status characters on
- Xstdout that present a visual display of what is happening. If
- Xsingle-pass mode is used for regular processing, this output can be
- Xredirected to /dev/null.
- X.Sp
- XThe output definitions:
- X.br
- X \&'.' = group's entry is up-to-date
- X.br
- X \&':' = group processed -- no change
- X.br
- X \&'#' = group processed
- X.br
- X \&'-' = group processed -- is now empty
- X.br
- X \&'x' = group excluded in active
- X.br
- X \&'X' = group excluded in active2
- X.br
- X \&'*' = chdir failed (might be ok)
- X.br
- X \&'!' = write failed (is NOT ok)
- X.br
- X \&'e' = informational error
- X.br
- X \&'E' = database-affecting error -- please report!
- X.SH CONFIGURATION
- XDuring the configuration of
- X.I trn
- Xa choice was made about where to place the thread data files.
- XThey either exist as a .thread file in each group's spool directory, or
- Xthey are a group.th file in a one-off directory structure on another drive.
- XSee the THREAD_DIR definition in config.h to review or change this definition.
- X.SH REBUILDING
- XIf the thread files are ever removed, also remove the file db.init in
- Xthe RNLIB directory.
- XThis file contains the byte-order of the machine that generated the database,
- Xand needs to be removed to truly start from scratch.
- XAn easy way to get
- X.I mthreads
- Xto remove all the files except for db.init is to specify the command:
- X.IP
- Xmthreads !all
- X.PP
- XThis also turns off thread processing for all groups.
- X.SH "ERROR HANDLING"
- XIf the active2 file is removed or corrupted, it will
- Xbe automatically rebuilt in the normal course of operation.
- XThe record of which groups should be threaded will be lost, however.
- XMissing/corrupted thread files are automatically re-built.
- X.SH EXAMPLES
- XRecommended commands to run on a regular basis are:
- X.IP
- Xmthreads -adve0630
- X.PP
- Xto start up an mthreads daemon in verbose logging mode that automatically
- Xthreads new groups and performs an extended expire at 6:30 am, or:
- X.IP
- Xmthreads -e >/dev/null
- X.PP
- Xto run an mthreads single-pass with extended expire that leaves new groups
- Xunthreaded.
- X.SH FILES
- X/usr/lib/news/active
- X.br
- X$RNLIB/active2
- X.br
- X$RNLIB/mt.log
- X.br
- X$RNLIB/db.init
- X.br
- X$RNLIB/LOCKmthreads
- X.br
- XLots of thread data files.
- X.SH AUTHOR
- XWayne Davison <davison@borland.com>
- END_OF_FILE
- if test 9578 -ne `wc -c <'mthreads.1'`; then
- echo shar: \"'mthreads.1'\" unpacked with wrong size!
- fi
- # end of 'mthreads.1'
- fi
- if test -f 'ngdata.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ngdata.c'\"
- else
- echo shar: Extracting \"'ngdata.c'\" \(8913 characters\)
- sed "s/^X//" >'ngdata.c' <<'END_OF_FILE'
- X/* $Header: ngdata.c,v 4.3.3.2 91/01/16 03:18:21 davison Trn $
- X *
- X * $Log: ngdata.c,v $
- X * Revision 4.3.3.2 91/01/16 03:18:21 davison
- X * Integrated rn patches 48-54. Fixed bug in ZEROGLOB code.
- X *
- X * Revision 4.3.3.1 90/07/21 20:28:27 davison
- X * Initial Trn Release
- X *
- X * Revision 4.3.2.11 90/11/22 16:14:34 sob
- X * Added changes to accomodate picky C preprocessors
- X *
- X * Revision 4.3.2.10 90/04/14 22:05:15 sob
- X * Removed redundant declaration of active_name
- X *
- X * Revision 4.3.2.9 90/03/22 23:04:55 sob
- X * Fixes provided by Wayne Davison <drivax!davison>
- X *
- X * Revision 4.3.2.8 90/03/17 20:50:51 sob
- X * Fixes provided by stewart@netxcom.iad-nxe.global-mis.dhl.com to handle
- X * flaky transfers of the active file from the server.
- X *
- X * Revision 4.3.2.7 90/03/17 17:11:08 sob
- X * Added support for CNEWS active file flags.
- X *
- X * Revision 4.3.2.6 89/12/08 22:42:04 sob
- X * Corrected typo in an #ifdef statement pointed out by
- X * jik@pit-manager.mit.edu
- X *
- X * Revision 4.3.2.5 89/11/28 01:51:14 sob
- X * Removed redundant #include directive.
- X *
- X * Revision 4.3.2.4 89/11/27 01:31:07 sob
- X * Altered NNTP code per ideas suggested by Bela Lubkin
- X * <filbo@gorn.santa-cruz.ca.us>
- X *
- X * Revision 4.3.2.3 89/11/08 02:41:40 sob
- X * Removed unneeded subroutine.
- X *
- X * Revision 4.3.2.2 89/11/08 02:24:31 sob
- X * Integrated modifications from other RRN patches colleceted from USENET
- X *
- X * Revision 4.3.2.1 89/11/06 00:42:43 sob
- X * Added RRN support from NNTP 1.5
- X *
- X * Revision 4.3 85/05/01 11:44:38 lwall
- X * Baseline for release with 4.3bsd.
- X *
- X */
- X
- X#include "EXTERN.h"
- X#include "common.h"
- X#include "ndir.h"
- X#include "rcstuff.h"
- X#include "rn.h"
- X#include "intrp.h"
- X#include "final.h"
- X#include "rcln.h"
- X#include "util.h"
- X#ifdef SERVER
- X#include "server.h"
- X#endif
- X#include "INTERN.h"
- X#include "ngdata.h"
- X
- Xvoid
- Xngdata_init()
- X{
- X#ifdef SERVER
- X char ser_line[256];
- X int entries;
- X#endif
- X char *cp;
- X
- X/* The following is only for systems that do not zero globals properly */
- X#ifdef ZEROGLOB
- X# ifdef CACHEFIRST
- X {
- X int i;
- X for (i=0; i<MAXRCLINE; i++)
- X abs1st[i] = 0;
- X }
- X# endif
- X#endif /* ZEROGLOB */
- X
- X /* open the active file */
- X
- X#ifdef SERVER
- X
- X#ifdef USETHREADS
- X if (use_threads) {
- X cp = filexp(ACTIVE2);
- X actfp = fopen(cp,"r");
- X if (actfp == Nullfp) {
- X printf(cantopen,cp) FLUSH;
- X finalize(1);
- X }
- X return;
- X }
- X#endif
- X
- X put_server("LIST"); /* tell server we want the active file */
- X get_server(ser_line, sizeof(ser_line));
- X if (*ser_line != CHAR_OK) { /* and then see if that's ok */
- X fprintf(stdout, "Can't get active file from server: \n%s\n", ser_line);
- X finalize(1);
- X }
- X
- X cp = filexp("/tmp/rrnact.%$"); /* make a temporary name */
- X strcpy(active_name, cp);
- X actfp = fopen(active_name, "w+"); /* and get ready */
- X if (actfp == Nullfp) {
- X printf(cantopen,active_name) FLUSH;
- X finalize(1);
- X }
- X
- X entries = 0;
- X while (1) {
- X if (get_server(ser_line, sizeof(ser_line)) < 0) {
- X printf("Can't get active file from server:\ntransfer failed after %d entries\n", entries);
- X finalize(1);
- X }
- X if (ser_line[0] == '.') /* while there's another line */
- X break; /* get it and write it to */
- X entries++;
- X fputs(ser_line, actfp);
- X putc('\n', actfp);
- X }
- X
- X fseek(actfp,0L,0); /* just get to the beginning */
- X
- X#else /* not SERVER */
- X
- X#ifdef USETHREADS
- X if (use_threads)
- X cp = filexp(ACTIVE2);
- X else
- X#endif
- X cp = filexp(ACTIVE);
- X actfp = fopen(cp,"r");
- X if (actfp == Nullfp) {
- X printf(cantopen,cp) FLUSH;
- X finalize(1);
- X }
- X#endif
- X}
- X
- X/* find the maximum article number of a newsgroup */
- X
- XART_NUM
- Xgetngsize(num)
- Xregister NG_NUM num;
- X{
- X register int len;
- X register char *nam;
- X char tmpbuf[80];
- X ART_POS oldsoft;
- X
- X nam = rcline[num];
- X len = rcnums[num] - 1;
- X softtries++;
- X#ifdef DEBUGGING
- X if (debug & DEB_SOFT_POINTERS)
- X printf("Softptr = %ld\n",(long)softptr[num]) FLUSH;
- X#endif
- X oldsoft = softptr[num];
- X if ((softptr[num] = findact(tmpbuf, nam, len, (long)oldsoft)) >= 0) {
- X if (softptr[num] != oldsoft) {
- X softmisses++;
- X writesoft = TRUE;
- X }
- X }
- X else {
- X softptr[num] = 0;
- X if (rcchar[num] == ':') /* unsubscribe quietly */
- X rcchar[num] = NEGCHAR;
- X return TR_BOGUS; /* well, not so quietly, actually */
- X }
- X
- X#ifdef DEBUGGING
- X if (debug & DEB_SOFT_POINTERS) {
- X printf("Should be %ld\n",(long)softptr[num]) FLUSH;
- X }
- X#endif
- X#ifdef MININACT
- X {
- X register char *s, ch;
- X ART_NUM tmp;
- X
- X for (s=tmpbuf+len+1; isdigit(*s); s++) ;
- X if (tmp = atol(s))
- X#ifdef CACHEFIRST
- X abs1st[num] = tmp;
- X#else
- X abs1st = tmp;
- X#endif
- X if (!in_ng) {
- X for (s++; isdigit(*s); s++) ;
- X while (isspace(*s)) s++;
- X ch = *s;
- X#ifdef USETHREADS
- X if (isupper(ch)) {
- X ch = tolower(ch);
- X ThreadedGroup = FALSE;
- X } else
- X ThreadedGroup = use_threads;
- X#endif
- X switch (ch) {
- X case 'n': moderated = getval("NOPOSTRING"," (no posting)"); break;
- X case 'm': moderated = getval("MODSTRING", " (moderated)"); break;
- X /* This shouldn't even occur. What are we doing in a non-existent
- X group? Disallow it. */
- X case 'x': return TR_BOGUS;
- X /* what should be done about refiled groups? rn shouldn't even
- X be in them (ie, if sci.aquaria is refiled to rec.aquaria, then
- X get the news there) */
- X case '=': return TR_BOGUS;
- X default: moderated = nullstr;
- X }
- X }
- X }
- X#endif
- X return atol(tmpbuf+len+1);
- X}
- X
- XACT_POS
- Xfindact(outbuf,nam,len,suggestion)
- Xchar *outbuf;
- Xchar *nam;
- Xint len;
- Xlong suggestion;
- X{
- X ACT_POS retval;
- X
- X fseek(actfp,100000L,1); /* hopefully this forces a reread */
- X if (suggestion == 0L || fseek(actfp,suggestion,0) < 0 ||
- X fgets(outbuf,80,actfp) == Nullch ||
- X outbuf[len] != ' ' ||
- X strnNE(outbuf,nam,len)) {
- X#ifdef DEBUGGING
- X if (debug & DEB_SOFT_POINTERS)
- X printf("Missed, looking for %s in %sLen = %d\n",nam,outbuf,len)
- X FLUSH;
- X#endif
- X fseek(actfp,0L,0);
- X#ifndef lint
- X retval = (ACT_POS)ftell(actfp);
- X#else
- X retval = Null(ACT_POS);
- X#endif /* lint */
- X while (fgets(outbuf,80,actfp) != Nullch) {
- X if (outbuf[len] == ' ' && strnEQ(outbuf,nam,len))
- X return retval;
- X#ifndef lint
- X retval = (ACT_POS) ftell(actfp);
- X#endif /* lint */
- X }
- X return (ACT_POS) -1; /* well, not so quietly, actually */
- X }
- X else
- X#ifndef lint
- X return (ACT_POS) suggestion;
- X#else
- X return retval;
- X#endif /* lint */
- X /*NOTREACHED*/
- X}
- X
- X/* determine the absolutely first existing article number */
- X#ifdef SERVER
- XART_NUM
- Xgetabsfirst(ngnum,ngsize)
- Xregister NG_NUM ngnum;
- XART_NUM ngsize;
- X{
- X register ART_NUM a1st;
- X#ifndef MININACT
- X char ser_line[256];
- X ART_NUM x,y;
- X#endif
- X
- X#ifdef CACHEFIRST
- X if (a1st = abs1st[ngnum])
- X return a1st;
- X#endif
- X#ifdef MININACT
- X getngsize(ngnum);
- X# ifdef CACHEFIRST
- X return abs1st[ngnum];
- X# else
- X return abs1st;
- X# endif
- X#else
- X sprintf(cp,"GROUP %s",rcline[ngnum]);
- X put_server(cp);
- X if (get_server(ser_line, sizeof(ser_line)) < 0) {
- X fprintf(stderr, "rrn: Unexpected close of server socket.\n");
- X finalize(1);
- X }
- X if (*ser_line != CHAR_OK) { /* and then see if that's ok */
- X a1st = ngsize+1; /* nothing there */
- X }
- X (void) sscanf(ser_line,"%d%d%d",&x,&y,&a1st);
- X# ifdef CACHEFIRST
- X abs1st[ngnum] = a1st;
- X# endif
- X return a1st;
- X#endif
- X}
- X/* we already know the lowest article number with NNTP */
- XART_NUM
- Xgetngmin(dirname,floor)
- Xchar *dirname;
- XART_NUM floor;
- X{
- X return(floor);
- X}
- X#else
- XART_NUM
- Xgetabsfirst(ngnum,ngsize)
- Xregister NG_NUM ngnum;
- XART_NUM ngsize;
- X{
- X register ART_NUM a1st;
- X#ifndef MININACT
- X char dirname[MAXFILENAME];
- X#endif
- X
- X#ifdef CACHEFIRST
- X if (a1st = abs1st[ngnum])
- X return a1st;
- X#endif
- X#ifdef MININACT
- X getngsize(ngnum);
- X# ifdef CACHEFIRST
- X return abs1st[ngnum];
- X# else
- X return abs1st;
- X# endif
- X#else /* not MININACT */
- X sprintf(dirname,"%s/%s",spool,getngdir(rcline[ngnum]));
- X a1st = getngmin(dirname,0L);
- X if (!a1st) /* nothing there at all? */
- X a1st = ngsize+1; /* aim them at end of newsgroup */
- X# ifdef CACHEFIRST
- X abs1st[ngnum] = a1st;
- X# endif
- X return a1st;
- X#endif /* MININACT */
- X}
- X
- X/* scan a directory for minimum article number greater than floor */
- X
- XART_NUM
- Xgetngmin(dirname,floor)
- Xchar *dirname;
- XART_NUM floor;
- X{
- X register DIR *dirp;
- X register struct DIRTYPE *dp;
- X register ART_NUM min = 1000000;
- X register ART_NUM maybe;
- X register char *p;
- X char tmpbuf[128];
- X
- X dirp = opendir(dirname);
- X if (!dirp)
- X return 0;
- X while ((dp = readdir(dirp)) != Null(struct DIRTYPE *)) {
- X if ((maybe = atol(dp->d_name)) < min && maybe > floor) {
- X for (p = dp->d_name; *p; p++)
- X if (!isdigit(*p))
- X goto nope;
- X if (*dirname == '.' && !dirname[1])
- X stat(dp->d_name, &filestat);
- X else {
- X sprintf(tmpbuf,"%s/%s",dirname,dp->d_name);
- X stat(tmpbuf, &filestat);
- X }
- X if (! (filestat.st_mode & S_IFDIR))
- X min = maybe;
- X }
- X nope:
- X ;
- X }
- X closedir(dirp);
- X return min==1000000 ? 0 : min;
- X}
- X#endif
- END_OF_FILE
- if test 8913 -ne `wc -c <'ngdata.c'`; then
- echo shar: \"'ngdata.c'\" unpacked with wrong size!
- fi
- # end of 'ngdata.c'
- fi
- if test -f 'ngstuff.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ngstuff.c'\"
- else
- echo shar: Extracting \"'ngstuff.c'\" \(10924 characters\)
- sed "s/^X//" >'ngstuff.c' <<'END_OF_FILE'
- X/* $Header: ngstuff.c,v 4.3.3.3 91/01/16 03:18:25 davison Trn $
- X *
- X * $Log: ngstuff.c,v $
- X * Revision 4.3.3.3 91/01/16 03:18:25 davison
- X * Changed some expressions to registers to bypass a compiler problem.
- X *
- X * Revision 4.3.3.2 90/08/20 18:29:08 davison
- X * Expanded path arrays for consistancy.
- X *
- X * Revision 4.3.3.1 90/07/21 20:29:12 davison
- X * Initial Trn Release
- X *
- X * Revision 4.3.2.2 90/04/14 19:40:02 sob
- X * Fixed small syntax problem that generates errors with particular C
- X * preprocessors.
- X *
- X * Revision 4.3.1.2 85/05/10 14:31:52 lwall
- X * Prevented "Junked" or "Marked unread" when no state change.
- X *
- X * Revision 4.3.1.1 85/05/10 11:36:45 lwall
- X * Branch for patches.
- X *
- X * Revision 4.3 85/05/01 11:45:03 lwall
- X * Baseline for release with 4.3bsd.
- X *
- X */
- X
- X#include "EXTERN.h"
- X#include "common.h"
- X#include "term.h"
- X#include "util.h"
- X#include "ng.h"
- X#include "bits.h"
- X#include "intrp.h"
- X#include "cheat.h"
- X#include "head.h"
- X#include "final.h"
- X#include "sw.h"
- X#ifdef USETHREADS
- X#include "rthreads.h"
- X#include "rn.h"
- X#include "rcstuff.h"
- X#endif
- X#include "uudecode.h"
- X#include "INTERN.h"
- X#include "ngstuff.h"
- X
- Xvoid
- Xngstuff_init()
- X{
- X ;
- X}
- X
- X/* do a shell escape */
- X
- Xint
- Xescapade()
- X{
- X register char *s;
- X bool interactive = (buf[1] == FINISHCMD);
- X bool docd;
- X char whereiam[512];
- X
- X if (!finish_command(interactive)) /* get remainder of command */
- X return -1;
- X s = buf+1;
- X docd = *s != '!';
- X if (!docd) {
- X s++;
- X }
- X else {
- X getwd(whereiam);
- X if (chdir(cwd)) {
- X printf(nocd,cwd) FLUSH;
- X sig_catcher(0);
- X }
- X }
- X while (*s == ' ') s++;
- X /* skip leading spaces */
- X interp(cmd_buf, (sizeof cmd_buf), s);/* interpret any % escapes */
- X resetty(); /* make sure tty is friendly */
- X doshell(Nullch,cmd_buf); /* invoke the shell */
- X noecho(); /* and make terminal */
- X crmode(); /* unfriendly again */
- X if (docd) {
- X if (chdir(whereiam)) {
- X printf(nocd,whereiam) FLUSH;
- X sig_catcher(0);
- X }
- X }
- X#ifdef MAILCALL
- X mailcount = 0; /* force recheck */
- X#endif
- X return 0;
- X}
- X
- X/* process & command */
- X
- Xint
- Xswitcheroo()
- X{
- X if (!finish_command(TRUE)) /* get rest of command */
- X return -1; /* if rubbed out, try something else */
- X if (!buf[1])
- X pr_switches();
- X#ifdef PUSHBACK
- X else if (buf[1] == '&') {
- X if (!buf[2]) {
- X page_init();
- X show_macros();
- X }
- X else {
- X char tmpbuf[LBUFLEN];
- X register char *s;
- X
- X for (s=buf+2; isspace(*s); s++);
- X mac_line(s,tmpbuf,(sizeof tmpbuf));
- X }
- X }
- X#endif
- X else {
- X bool docd = (instr(buf,"-d") != Nullch);
- X char whereami[512];
- X
- X if (docd)
- X getwd(whereami);
- X sw_list(buf+1);
- X if (docd) {
- X cwd_check();
- X if (chdir(whereami)) { /* -d does chdirs */
- X printf(nocd,whereami) FLUSH;
- X sig_catcher(0);
- X }
- X }
- X }
- X return 0;
- X}
- X
- X/* process range commands */
- X
- Xint
- Xnumnum()
- X{
- X ART_NUM min, max;
- X char *cmdlst = Nullch;
- X register char *s, *c;
- X ART_NUM oldart = art;
- X char tmpbuf[LBUFLEN];
- X bool justone = TRUE; /* assume only one article */
- X
- X perform_cnt = 0;
- X if (!finish_command(TRUE)) /* get rest of command */
- X return NN_INP;
- X if (lastart < 1) {
- X fputs("\nNo articles\n",stdout) FLUSH;
- X return NN_ASK;
- X }
- X#ifdef ARTSRCH
- X if (srchahead)
- X srchahead = -1;
- X#endif
- X for (s=buf; *s && (isdigit(*s) || index(" ,-.$",*s)); s++)
- X if (!isdigit(*s))
- X justone = FALSE;
- X if (*s) {
- X cmdlst = savestr(s);
- X justone = FALSE;
- X }
- X else if (!justone)
- X cmdlst = savestr("m");
- X *s++ = ',';
- X *s = '\0';
- X safecpy(tmpbuf,buf,LBUFLEN);
- X for (s = tmpbuf; c = index(s,','); s = ++c) {
- X *c = '\0';
- X if (*s == '.')
- X min = oldart;
- X else
- X min = atol(s);
- X#ifdef USETHREADS
- X if (min<absfirst && justone) {
- X int r;
- X
- X /* Check if this is a root number */
- X for (r = 0; r < total.root; r++) {
- X if (p_roots[r].root_num == min) {
- X p_art = p_articles + p_roots[r].articles;
- X art = p_art->num;
- X if (p_art->subject == -1) {
- X follow_thread('N');
- X }
- X return NN_REREAD;
- X }
- X }
- X }
- X#endif
- X if (min<absfirst) { /* make sure it is reasonable */
- X min = absfirst;
- X printf("(First article is %ld)\n",(long)absfirst) FLUSH;
- X pad(just_a_sec/3);
- X }
- X if ((s=index(s,'-')) != Nullch) {
- X s++;
- X if (*s == '$')
- X max = lastart;
- X else if (*s == '.')
- X max = oldart;
- X else
- X max = atol(s);
- X }
- X else
- X max = min;
- X if (max>lastart) {
- X max = lastart;
- X if (min > max)
- X min = max;
- X printf("(Last article is %ld)\n",(long)lastart) FLUSH;
- X pad(just_a_sec/3);
- X }
- X if (max < min) {
- X fputs("\nBad range\n",stdout) FLUSH;
- X if (cmdlst)
- X free(cmdlst);
- X return NN_ASK;
- X }
- X if (justone) {
- X art = min;
- X return NN_REREAD;
- X }
- X check_first(min);
- X for (art=min; art<=max; art++) {
- X if (perform(cmdlst,TRUE)) {
- X#ifdef VERBOSE
- X IF(verbose)
- X printf("\n(Interrupted at article %ld)\n",(long)art)
- X FLUSH;
- X ELSE
- X#endif
- X#ifdef TERSE
- X printf("\n(Intr at %ld)\n",(long)art) FLUSH;
- X#endif
- X if (cmdlst)
- X free(cmdlst);
- X return NN_ASK;
- X }
- X }
- X }
- X art = oldart;
- X if (cmdlst)
- X free(cmdlst);
- X return NN_NORM;
- X}
- X
- X#ifdef USETHREADS
- Xint
- Xuse_selected()
- X{
- X PACKED_ARTICLE *root_limit;
- X register char *s, ch;
- X register int r;
- X char *cmdstr;
- X int ret = 1, orig_root_cnt = selected_root_cnt;
- X
- X if (!finish_command(TRUE)) /* get rest of command */
- X return 0;
- X if (!(ch = buf[1]))
- X return -1;
- X cmdstr = savestr(buf+1);
- X
- X perform_cnt = 0;
- X page_line = 1;
- X
- X /* Multiple commands and commands that operate on individual articles
- X ** use the article loop.
- X */
- X if (strlen(cmdstr) > 1 || index("ejmMsSwW|=", ch)) {
- X bool want_unread = (unread_selector || ch == 'm');
- X
- X for (r = 0; r < total.root; r++) {
- X if (scan_all_roots
- X || (!orig_root_cnt&&root_article_cnts[r]&&!(selected_roots[r]&4))
- X || (selected_roots[r] & (unread_selector+1))) {
- X p_art = p_articles + p_roots[r].articles;
- X root_limit = upper_limit( p_art, 0 );
- X for (; p_art < root_limit; p_art++) {
- X art = p_art->num;
- X if (p_art->subject != -1
- X && (!was_read(art) ^ want_unread)) {
- X if (perform(cmdstr, TRUE)) {
- X fputs("\nInterrupted\n", stdout) FLUSH;
- X goto break_out;
- X }
- X }
- X if (p_art == Nullart)
- X break;
- X }/* for all articles */
- X }/* if selected */
- X }/* for all threads */
- X } /* other commands get the root loop */
- X else if (ch == '+' || ch == '-' || ch == 'J' || ch == 'T' || ch == 't') {
- X for (r = 0; r < total.root; r++) {
- X if (scan_all_roots
- X || (!orig_root_cnt&&root_article_cnts[r]&&!(selected_roots[r]&4))
- X || (selected_roots[r] & (unread_selector+1))) {
- X if (mode != 't' && ch != 't') {
- X printf("T%-5ld ", (long)p_roots[r].root_num);
- X }
- X p_art = p_articles + p_roots[r].articles;
- X art = p_art->num;
- X if (perform(cmdstr, FALSE)) {
- X fputs("\nInterrupted\n", stdout) FLUSH;
- X goto break_out;
- X }
- X#ifdef VERBOSE
- X IF(verbose)
- X if (mode != 't' && ch != 't' && ch != 'T')
- X putchar('\n') FLUSH;
- X#endif
- X }
- X }
- X }
- X else if (ch == 'E') { /* one command needs no looping at all */
- X if (uu_out != Nullfp) {
- X uud_end();
- X } else {
- X ret = 2;
- X }
- X }
- X else {
- X printf("???%s\n",cmdstr);
- X ret = -1;
- X }
- X break_out:
- X free(cmdstr);
- X return ret;
- X}
- X#endif
- X
- Xint
- Xperform(cmdlst,toplevel)
- Xregister char *cmdlst;
- Xint toplevel;
- X{
- X register int ch;
- X
- X if (toplevel) {
- X printf("%-6ld ",art);
- X fflush(stdout);
- X }
- X perform_cnt++;
- X for (; ch = *cmdlst; cmdlst++) {
- X if (isspace(ch) || ch == ':')
- X continue;
- X if (ch == 'j') {
- X if (!was_read(art)) {
- X mark_as_read();
- X#ifdef VERBOSE
- X IF(verbose)
- X fputs("\tJunked",stdout);
- X#endif
- X }
- X }
- X#ifdef USETHREADS
- X else if (ch == '+') {
- X register char mask = unread_selector+1;
- X find_article(art);
- X if (p_art && !(selected_roots[p_art->root] & mask)) {
- X register int r = p_art->root;
- X selected_roots[r] |= mask;
- X selected_root_cnt++;
- X if (mode == 't') {
- X selected_count += root_article_cnts[r];
- X } else {
- X selected_count += count_one_root(r);
- X#ifdef VERBOSE
- X IF(verbose)
- X fputs("\tSelected",stdout);
- X#endif
- X }
- X }
- X }
- X else if (ch == '-') {
- X register char mask = unread_selector+1;
- X find_article(art);
- X if (p_art && selected_root_cnt
- X && (selected_roots[p_art->root] & mask)) {
- X register int r = p_art->root;
- X selected_roots[r] &= ~mask;
- X selected_root_cnt--;
- X if (mode == 't') {
- X selected_count -= root_article_cnts[r];
- X } else {
- X selected_count -= count_one_root(r);
- X#ifdef VERBOSE
- X IF(verbose)
- X fputs("\tDeselected",stdout);
- X#endif
- X }
- X }
- X }
- X else if (ch == 't') {
- X find_article(art);
- X entire_tree();
- X }
- X else if (ch == 'J' || ch == 'T') {
- X char tmpbuf[128];
- X ART_NUM oldart = art;
- X
- X find_article(art);
- X if (p_art) {
- X if (ch == 'T') {
- X sprintf(tmpbuf,"T%ld\t# %s",
- X (long)p_roots[p_art->root].root_num,
- X subject_ptrs[p_art->subject]);
- X fputs(tmpbuf,stdout);
- X kf_append(tmpbuf);
- X }
- X follow_thread('J');
- X art = oldart;
- X }
- X }
- X#endif
- X else if (ch == 'm') {
- X if (was_read(art)) {
- X unmark_as_read();
- X#ifdef VERBOSE
- X IF(verbose)
- X fputs("\tMarked unread",stdout);
- X#endif
- X }
- X }
- X else if (ch == 'M') {
- X#ifdef DELAYMARK
- X delay_unmark(art);
- X#ifdef VERBOSE
- X IF(verbose)
- X fputs("\tWill return",stdout);
- X#endif
- X#else
- X notincl("M");
- X return -1;
- X#endif
- X }
- X else if (ch == '=') {
- X printf("\t%s",fetchsubj(art,FALSE,FALSE));
- X#ifdef VERBOSE
- X IF(verbose)
- X ;
- X ELSE
- X#endif
- X putchar('\n') FLUSH; /* ghad! */
- X }
- X else if (ch == 'C') {
- X#ifdef ASYNC_PARSE
- X printf("\t%sancelled",(cancel_article() ? "Not c" : "C"));
- X#else
- X notincl("C");
- X return -1;
- X#endif
- X }
- X else if (ch == '%') {
- X#ifdef ASYNC_PARSE
- X char tmpbuf[512];
- X
- X if (one_command)
- X interp(tmpbuf, (sizeof tmpbuf), cmdlst);
- X else
- X cmdlst = dointerp(tmpbuf, (sizeof tmpbuf), cmdlst, ":") - 1;
- X perform_cnt--;
- X if (perform(tmpbuf,FALSE))
- X return -1;
- X#else
- X notincl("%");
- X return -1;
- X#endif
- X }
- X else if (index("!&sSwWe|",ch)) {
- X if (one_command)
- X strcpy(buf,cmdlst);
- X else
- X cmdlst = cpytill(buf,cmdlst,':') - 1;
- X /* we now have the command in buf */
- X if (ch == '!') {
- X escapade();
- X#ifdef VERBOSE
- X IF(verbose)
- X fputs("\tShell escaped",stdout);
- X#endif
- X }
- X else if (ch == '&') {
- X switcheroo();
- X#ifdef VERBOSE
- X IF(verbose)
- X if (buf[1] && buf[1] != '&')
- X fputs("\tSwitched",stdout);
- X#endif
- X }
- X else {
- X putchar('\t');
- X save_article();
- X#ifdef VERBOSE
- X IF(verbose)
- X ;
- X ELSE
- X#endif
- X putchar('\n') FLUSH;
- X }
- X }
- X else {
- X printf("\t???%s\n",cmdlst);
- X return -1;
- X }
- X#ifdef VERBOSE
- X fflush(stdout);
- X#endif
- X if (one_command)
- X break;
- X }
- X if (toplevel) {
- X#ifdef VERBOSE
- X IF(verbose)
- X putchar('\n') FLUSH;
- X#endif
- X }
- X if( int_count ) {
- X int_count = 0;
- X return -1;
- X }
- X return 0;
- X}
- END_OF_FILE
- if test 10924 -ne `wc -c <'ngstuff.c'`; then
- echo shar: \"'ngstuff.c'\" unpacked with wrong size!
- fi
- # end of 'ngstuff.c'
- fi
- if test -f 'term.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'term.h'\"
- else
- echo shar: Extracting \"'term.h'\" \(8474 characters\)
- sed "s/^X//" >'term.h' <<'END_OF_FILE'
- X/* $Header: term.h,v 4.3.3.2 91/01/16 03:38:39 davison Trn $
- X *
- X * $Log: term.h,v $
- X * Revision 4.3.3.2 91/01/16 03:38:39 davison
- X * Integrated rn patches 48-54. Added optional prototyping.
- X *
- X * Revision 4.3.3.1 90/06/20 22:40:34 davison
- X * Initial Trn Release
- X *
- X * Revision 4.3.2.6 90/12/10 01:32:08 sob
- X * Hopefully, the rn -e -L problem is now fixed.
- X *
- X * Revision 4.3.2.5 90/11/22 13:48:09 sob
- X * Backed out change in Patch 48.
- X *
- X * Revision 4.3.2.4 90/11/05 23:54:49 sob
- X * changed maybe_eol to test when erase_screen is FALSE intstead of TRUE.
- X *
- X * Revision 4.3.2.3 90/10/01 01:49:39 sob
- X * Changed ospeed from short to long.
- X *
- X * Revision 4.3.2.2 90/04/06 20:35:34 sob
- X * Added fixes for SCO Xenix sent by ronald@robobar.co.uk.
- X *
- X * Revision 4.3.2.1 89/11/28 01:54:03 sob
- X * Added better support for SIGWINCH.
- X *
- X * Revision 4.3.1.2 85/05/13 15:52:05 lwall
- X * Declared devtty on TERMIO system.
- X *
- X * Revision 4.3.1.1 85/05/10 11:41:24 lwall
- X * Branch for patches.
- X *
- X * Revision 4.3 85/05/01 11:51:36 lwall
- X * Baseline for release with 4.3bsd.
- X *
- X */
- X
- X#ifdef PUSHBACK
- XEXT char circlebuf[PUSHSIZE];
- XEXT int nextin INIT(0);
- XEXT int nextout INIT(0);
- X#ifdef PENDING
- X#ifdef FIONREAD
- XEXT long iocount INIT(0);
- X#ifndef lint
- X#define input_pending() (nextin!=nextout || (ioctl(0, FIONREAD, &iocount),(int)iocount))
- X#else
- X#define input_pending() bizarre
- X#endif /* lint */
- X#else /* FIONREAD */
- X#ifdef RDCHK
- X#define input_pending() (rdchk(0) > 0) /* boolean only */
- X#else /* RDCHK */
- Xint circfill();
- XEXT int devtty INIT(0);
- X#ifndef lint
- X#define input_pending() (nextin!=nextout || circfill())
- X#else
- X#define input_pending() bizarre
- X#endif /* lint */
- X#endif /* RDCHK */
- X#endif /* FIONREAD */
- X#else /* PENDING */
- X#ifndef lint
- X#define input_pending() (nextin!=nextout)
- X#else
- X#define input_pending() bizarre
- X#endif /* lint */
- X#endif /* PENDING */
- X#else /* PUSHBACK */
- X#ifdef PENDING
- X#ifdef FIONREAD /* must have FIONREAD or O_NDELAY for input_pending() */
- X#define read_tty(addr,size) read(0,addr,size)
- X#ifndef lint
- X#define input_pending() (ioctl(0, FIONREAD, &iocount),(int)iocount)
- X#else
- X#define input_pending() bizarre
- X#endif /* lint */
- XEXT long iocount INIT(0);
- X
- X#else /* FIONREAD */
- X
- X#ifdef RDCHK
- X#define input_pending() (rdchk(0) > 0) /* boolean only */
- X#else /* RDCHK */
- X
- XEXT int devtty INIT(0);
- XEXT bool is_input INIT(FALSE);
- XEXT char pending_ch INIT(0);
- X#ifndef lint
- X#define input_pending() (is_input || (is_input=read(devtty,&pending_ch,1)))
- X#else
- X#define input_pending() bizarre
- X#endif /* lint */
- X#endif /* RDCHK */
- X#endif /* FIONREAD */
- X#else /* PENDING */
- X#define read_tty(addr,size) read(0,addr,size)
- X#define input_pending() (FALSE)
- X#endif /* PENDING */
- X#endif /* PUSHBACK */
- X
- X/* stuff wanted by terminal mode diddling routines */
- X
- X#ifdef TERMIO
- XEXT struct termio _tty, _oldtty;
- X#else
- XEXT struct sgttyb _tty;
- XEXT int _res_flg INIT(0);
- X#endif
- X
- XEXT int _tty_ch INIT(2);
- XEXT bool bizarre INIT(FALSE); /* do we need to restore terminal? */
- X
- X/* terminal mode diddling routines */
- X
- X#ifdef TERMIO
- X
- X#define crmode() ((bizarre=1),_tty.c_lflag &=~ICANON,_tty.c_cc[VMIN] = 1,ioctl(_tty_ch,TCSETAF,&_tty))
- X#define nocrmode() ((bizarre=1),_tty.c_lflag |= ICANON,_tty.c_cc[VEOF] = CEOF,stty(_tty_ch,&_tty))
- X#define echo() ((bizarre=1),_tty.c_lflag |= ECHO, ioctl(_tty_ch, TCSETA, &_tty))
- X#define noecho() ((bizarre=1),_tty.c_lflag &=~ECHO, ioctl(_tty_ch, TCSETA, &_tty))
- X#define nl() ((bizarre=1),_tty.c_iflag |= ICRNL,_tty.c_oflag |= ONLCR,ioctl(_tty_ch, TCSETAW, &_tty))
- X#define nonl() ((bizarre=1),_tty.c_iflag &=~ICRNL,_tty.c_oflag &=~ONLCR,ioctl(_tty_ch, TCSETAW, &_tty))
- X#define savetty() (ioctl(_tty_ch, TCGETA, &_oldtty),ioctl(_tty_ch, TCGETA, &_tty))
- X#define resetty() ((bizarre=0),ioctl(_tty_ch, TCSETAF, &_oldtty))
- X#define unflush_output()
- X
- X#else
- X
- X#define raw() ((bizarre=1),_tty.sg_flags|=RAW, stty(_tty_ch,&_tty))
- X#define noraw() ((bizarre=1),_tty.sg_flags&=~RAW,stty(_tty_ch,&_tty))
- X#define crmode() ((bizarre=1),_tty.sg_flags |= CBREAK, stty(_tty_ch,&_tty))
- X#define nocrmode() ((bizarre=1),_tty.sg_flags &= ~CBREAK,stty(_tty_ch,&_tty))
- X#define echo() ((bizarre=1),_tty.sg_flags |= ECHO, stty(_tty_ch, &_tty))
- X#define noecho() ((bizarre=1),_tty.sg_flags &= ~ECHO, stty(_tty_ch, &_tty))
- X#define nl() ((bizarre=1),_tty.sg_flags |= CRMOD,stty(_tty_ch, &_tty))
- X#define nonl() ((bizarre=1),_tty.sg_flags &= ~CRMOD, stty(_tty_ch, &_tty))
- X#define savetty() (gtty(_tty_ch, &_tty), _res_flg = _tty.sg_flags)
- X#define resetty() ((bizarre=0),_tty.sg_flags = _res_flg, stty(_tty_ch, &_tty))
- X#ifdef LFLUSHO
- X#ifndef lint
- XEXT int lflusho INIT(LFLUSHO);
- X#else
- XEXT long lflusho INIT(LFLUSHO);
- X#endif /* lint */
- X#define unflush_output() (ioctl(_tty_ch,TIOCLBIC,&lflusho))
- X#else
- X#define unflush_output()
- X#endif /* LFLUSHO */
- X#endif /* TERMIO */
- X
- X#ifdef TIOCSTI
- X#ifdef lint
- X#define forceme(c) ioctl(_tty_ch,TIOCSTI,Null(long*)) /* ghad! */
- X#else
- X#define forceme(c) ioctl(_tty_ch,TIOCSTI,c) /* pass character in " " */
- X#endif /* lint */
- X#else
- X#define forceme(c)
- X#endif
- X
- X/* termcap stuff */
- X
- X/*
- X * NOTE: if you don't have termlib you'll either have to define these strings
- X * and the tputs routine, or you'll have to redefine the macros below
- X */
- X
- X#ifdef HAVETERMLIB
- XEXT char *BC INIT(Nullch); /* backspace character */
- XEXT char *UP INIT(Nullch); /* move cursor up one line */
- XEXT char *CR INIT(Nullch); /* get to left margin, somehow */
- XEXT char *VB INIT(Nullch); /* visible bell */
- XEXT char *CL INIT(Nullch); /* home and clear screen */
- XEXT char *CE INIT(Nullch); /* clear to end of line */
- X#if defined(CLEAREOL) || defined(USETHREADS)
- XEXT char *CM INIT(Nullch); /* cursor motion */
- XEXT char *HO INIT(Nullch); /* home cursor */
- X#endif
- X#ifdef CLEAREOL
- XEXT char *CD INIT(Nullch); /* clear to end of display */
- X#endif /* CLEAREOL */
- XEXT char *SO INIT(Nullch); /* begin standout mode */
- XEXT char *SE INIT(Nullch); /* end standout mode */
- XEXT int SG INIT(0); /* blanks left by SO and SE */
- XEXT char *US INIT(Nullch); /* start underline mode */
- XEXT char *UE INIT(Nullch); /* end underline mode */
- XEXT char *UC INIT(Nullch); /* underline a character, if that's how it's done */
- XEXT int UG INIT(0); /* blanks left by US and UE */
- XEXT bool AM INIT(FALSE); /* does terminal have automatic margins? */
- XEXT bool XN INIT(FALSE); /* does it eat 1st newline after automatic wrap? */
- XEXT char PC INIT(0); /* pad character for use by tputs() */
- XEXT long ospeed INIT(0); /* terminal output speed, for use by tputs() */
- XEXT int LINES INIT(0), COLS INIT(0); /* size of screen */
- XEXT int just_a_sec INIT(960); /* 1 sec at current baud rate */
- X /* (number of nulls) */
- X
- X/* define a few handy macros */
- X
- X#define backspace() tputs(BC,0,putchr) FLUSH
- X#define clear() tputs(CL,LINES,putchr) FLUSH
- X#define erase_eol() tputs(CE,1,putchr) FLUSH
- X#ifdef CLEAREOL
- X#define clear_rest() tputs(CD,LINES,putchr) FLUSH
- X#define maybe_eol() if(erase_screen&&can_home_clear)tputs(CE,1,putchr) FLUSH
- X#endif /* CLEAREOL */
- X#define underline() tputs(US,1,putchr) FLUSH
- X#define un_underline() tputs(UE,1,putchr) FLUSH
- X#define underchar() tputs(UC,0,putchr) FLUSH
- X#define standout() tputs(SO,1,putchr) FLUSH
- X#define un_standout() tputs(SE,1,putchr) FLUSH
- X#define up_line() tputs(UP,1,putchr) FLUSH
- X#define carriage_return() tputs(CR,1,putchr) FLUSH
- X#define dingaling() tputs(VB,1,putchr) FLUSH
- X#else
- X ???????? /* up to you */
- X#endif
- X
- XEXT int page_line INIT(1); /* line number for paging in print_line (origin 1) */
- X
- Xvoid term_init ANSI((void));
- Xvoid term_set ANSI((char *));
- X#ifdef PUSHBACK
- Xvoid pushchar ANSI((char));
- Xvoid mac_init ANSI((char *));
- Xvoid mac_line ANSI((char *,char *,int));
- Xvoid show_macros ANSI((void));
- X#endif
- Xchar putchr ANSI((char)); /* routine for tputs to call */
- Xbool finish_command ANSI((int));
- Xvoid eat_typeahead ANSI((void));
- Xvoid settle_down ANSI((void));
- X#ifndef read_tty
- X int read_tty ANSI((char *,int));
- X#endif
- Xvoid underprint ANSI((char *));
- X#ifdef NOFIREWORKS
- X void no_sofire ANSI((void));
- X void no_ulfire ANSI((void));
- X#endif
- Xvoid getcmd ANSI((char *));
- Xint get_anything ANSI((void));
- Xvoid in_char ANSI((char *,char));
- Xint print_lines ANSI((char *,int));
- Xvoid page_init ANSI((void));
- Xvoid pad ANSI((int));
- Xvoid printcmd ANSI((void));
- Xvoid rubout ANSI((void));
- Xvoid reprint ANSI((void));
- X#if defined(CLEAREOL) || defined(USETHREADS)
- Xvoid home_cursor ANSI((void));
- X#endif
- X#ifdef USETHREADS
- Xvoid goto_line ANSI((int,int));
- X#endif
- X#ifdef SIGWINCH
- Xint winch_catcher ANSI((void));
- X#endif /* SIGWINCH */
- END_OF_FILE
- if test 8474 -ne `wc -c <'term.h'`; then
- echo shar: \"'term.h'\" unpacked with wrong size!
- fi
- # end of 'term.h'
- fi
- if test -f 'util.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'util.c'\"
- else
- echo shar: Extracting \"'util.c'\" \(10588 characters\)
- sed "s/^X//" >'util.c' <<'END_OF_FILE'
- X/* $Header: util.c,v 4.3.3.3 91/01/16 03:41:50 davison Trn $
- X *
- X * $Log: util.c,v $
- X * Revision 4.3.3.3 91/01/16 03:41:50 davison
- X * Integrated rn patches 48-54.
- X *
- X * Revision 4.3.3.2 90/08/20 16:51:44 davison
- X * Fixed getcwd call to not overflow any buffers.
- X *
- X * Revision 4.3.3.1 90/07/21 20:34:10 davison
- X * Initial Trn Release
- X *
- X * Revision 4.3.2.8 90/11/22 13:54:06 sob
- X * Made changes to keep more preprocessors happy.
- X *
- X * Revision 4.3.2.7 90/10/01 01:52:18 sob
- X * Altered the preprocessor defines on GETWD/GETCWD per suggestion by
- X * rsm@math.arizona.edu.
- X *
- X * Revision 4.3.2.6 90/04/23 00:24:42 sob
- X * A bit of clean up.
- X *
- X * Revision 4.3.2.5 90/03/17 21:34:21 sob
- X * Reworked VOIDSIG into SIGRET.
- X *
- X * Revision 4.3.2.4 89/12/14 23:58:54 sob
- X * Fixed small bug reported by fletcher@cs.utexas.edu in getwd().
- X *
- X * Revision 4.3.2.3 89/11/08 04:47:11 sob
- X * Added VOIDSIG handling for SunOS 4.X
- X *
- X * Revision 4.3.2.2 89/11/07 23:19:35 sob
- X * Bug fixes for SIGSTP problems
- X *
- X * Revision 4.3.2.1 89/11/06 01:03:21 sob
- X * Added RRN support from NNTP 1.5
- X *
- X * Revision 4.3.1.2 85/05/15 14:44:27 lwall
- X * Last arg of execl changed from 0 to Nullch [(char*)0].
- X *
- X * Revision 4.3.1.1 85/05/10 11:41:30 lwall
- X * Branch for patches.
- X *
- X * Revision 4.3 85/05/01 11:51:44 lwall
- X * Baseline for release with 4.3bsd.
- X *
- X */
- X
- X#include "EXTERN.h"
- X#include "common.h"
- X#include "final.h"
- X#include "ndir.h"
- X#include "INTERN.h"
- X#include "util.h"
- X
- Xvoid
- Xutil_init()
- X{
- X ;
- X}
- X
- X/* fork and exec a shell command */
- X
- Xint
- Xdoshell(shl,s)
- Xchar *s, *shl;
- X{
- X int status, pid, w;
- X char *shell;
- X
- X#ifdef SIGTSTP
- X sigset(SIGTSTP,SIG_DFL);
- X sigset(SIGTTOU,SIG_DFL);
- X sigset(SIGTTIN,SIG_DFL);
- X#endif
- X if (shl != Nullch)
- X shell = shl;
- X else if ((shell = getenv("SHELL")) == Nullch || !*shell)
- X shell = PREFSHELL;
- X if ((pid = vfork()) == 0) {
- X#ifdef SERVER
- X int i;
- X
- X /* This is necessary to keep bourne shell from puking */
- X
- X for (i = 3; i < 10; ++i)
- X close(i);
- X#endif /* SERVER */
- X
- X if (*s)
- X execl(shell, shell, "-c", s, Nullch);
- X else
- X execl(shell, shell, Nullch, Nullch, Nullch);
- X _exit(127);
- X }
- X signal(SIGINT, SIG_IGN);
- X#ifdef SIGQUIT
- X signal(SIGQUIT, SIG_IGN);
- X#endif
- X waiting = TRUE;
- X while ((w = wait(&status)) != pid && w != -1)
- X ;
- X if (w == -1)
- X status = -1;
- X waiting = FALSE;
- X sigset(SIGINT, int_catcher); /* always catch interrupts */
- X#ifdef SIGQUIT
- X signal(SIGQUIT, SIG_DFL);
- X#endif
- X#ifdef SIGTSTP
- X sigset(SIGTSTP,stop_catcher);
- X sigset(SIGTTOU,stop_catcher);
- X sigset(SIGTTIN,stop_catcher);
- X#endif
- X return status;
- X}
- X
- Xstatic char nomem[] = "rn: out of memory!\n";
- X
- X/* paranoid version of malloc */
- X
- Xchar *
- Xsafemalloc(size)
- XMEM_SIZE size;
- X{
- X char *ptr;
- X char *malloc();
- X
- X ptr = malloc(size ? size : (MEM_SIZE)1);
- X if (ptr != Nullch)
- X return ptr;
- X else {
- X fputs(nomem,stdout) FLUSH;
- X sig_catcher(0);
- X }
- X /*NOTREACHED*/
- X}
- X
- X/* paranoid version of realloc */
- X
- Xchar *
- Xsaferealloc(where,size)
- Xchar *where;
- XMEM_SIZE size;
- X{
- X char *ptr;
- X char *realloc();
- X
- X ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
- X if (ptr != Nullch)
- X return ptr;
- X else {
- X fputs(nomem,stdout) FLUSH;
- X sig_catcher(0);
- X }
- X /*NOTREACHED*/
- X}
- X
- X/* safe version of string copy */
- X
- Xchar *
- Xsafecpy(to,from,len)
- Xchar *to;
- Xregister char *from;
- Xregister int len;
- X{
- X register char *dest = to;
- X
- X if (from != Nullch)
- X for (len--; len && (*dest++ = *from++); len--) ;
- X *dest = '\0';
- X return to;
- X}
- X
- X/* safe version of string concatenate, with \n deletion and space padding */
- X
- Xchar *
- Xsafecat(to,from,len)
- Xchar *to;
- Xregister char *from;
- Xregister int len;
- X{
- X register char *dest = to;
- X
- X len--; /* leave room for null */
- X if (*dest) {
- X while (len && *dest++) len--;
- X if (len) {
- X len--;
- X *(dest-1) = ' ';
- X }
- X }
- X if (from != Nullch)
- X while (len && (*dest++ = *from++)) len--;
- X if (len)
- X dest--;
- X if (*(dest-1) == '\n')
- X dest--;
- X *dest = '\0';
- X return to;
- X}
- X
- X/* copy a string up to some (non-backslashed) delimiter, if any */
- X
- Xchar *
- Xcpytill(to,from,delim)
- Xregister char *to, *from;
- Xregister int delim;
- X{
- X for (; *from; from++,to++) {
- X if (*from == '\\' && from[1] == delim)
- X from++;
- X else if (*from == delim)
- X break;
- X *to = *from;
- X }
- X *to = '\0';
- X return from;
- X}
- X
- X/* return ptr to little string in big string, NULL if not found */
- X
- Xchar *
- Xinstr(big, little)
- Xchar *big, *little;
- X
- X{
- X register char *t, *s, *x;
- X
- X for (t = big; *t; t++) {
- X for (x=t,s=little; *s; x++,s++) {
- X if (!*x)
- X return Nullch;
- X if (*s != *x)
- X break;
- X }
- X if (!*s)
- X return t;
- X }
- X return Nullch;
- X}
- X
- X/* effective access */
- X
- X#ifdef SETUIDGID
- Xint
- Xeaccess(filename, mod)
- Xchar *filename;
- Xint mod;
- X{
- X int protection, euid;
- X
- X mod &= 7; /* remove extraneous garbage */
- X if (stat(filename, &filestat) < 0)
- X return -1;
- X euid = geteuid();
- X if (euid == ROOTID)
- X return 0;
- X protection = 7 & (filestat.st_mode >>
- X (filestat.st_uid == euid ? 6 :
- X (filestat.st_gid == getegid() ? 3 : 0)
- X ));
- X if ((mod & protection) == mod)
- X return 0;
- X errno = EACCES;
- X return -1;
- X}
- X#endif
- X
- X/*
- X * Get working directory
- X */
- X#ifndef GETWD
- X#ifdef GETCWD
- Xchar *
- Xgetwd(np)
- Xchar *np;
- X{
- X char * name;
- X extern char * getcwd();
- X name = getcwd(np,512);
- X return(name);
- X}
- X#else
- Xchar *
- Xgetwd(np) /* shorter but slower */
- Xchar *np;
- X{
- X FILE *popen();
- X FILE *pipefp = popen("/bin/pwd","r");
- X
- X if (pipefp == Nullfp) {
- X printf("Can't run /bin/pwd\n") FLUSH;
- X finalize(1);
- X }
- X fgets(np,512,pipefp);
- X np[strlen(np)-1] = '\0'; /* wipe out newline */
- X pclose(pipefp);
- X return np;
- X}
- X#endif
- X#endif
- X/* just like fgets but will make bigger buffer as necessary */
- X
- Xchar *
- Xget_a_line(original_buffer,buffer_length,fp)
- Xchar *original_buffer;
- Xregister int buffer_length;
- XFILE *fp;
- X{
- X register int bufix = 0;
- X register int nextch;
- X register char *some_buffer_or_other = original_buffer;
- X
- X do {
- X if (bufix >= buffer_length) {
- X buffer_length *= 2;
- X if (some_buffer_or_other == original_buffer) {
- X /* currently static? */
- X some_buffer_or_other = safemalloc((MEM_SIZE)buffer_length+1);
- X strncpy(some_buffer_or_other,original_buffer,buffer_length/2);
- X /* so we must copy it */
- X }
- X else { /* just grow in place, if possible */
- X some_buffer_or_other = saferealloc(some_buffer_or_other,
- X (MEM_SIZE)buffer_length+1);
- X }
- X }
- X if ((nextch = getc(fp)) == EOF)
- X return Nullch;
- X some_buffer_or_other[bufix++] = (char) nextch;
- X } while (nextch && nextch != '\n');
- X some_buffer_or_other[bufix] = '\0';
- X len_last_line_got = bufix;
- X return some_buffer_or_other;
- X}
- X
- X/* copy a string to a safe spot */
- X
- Xchar *
- Xsavestr(str)
- Xchar *str;
- X{
- X register char *newaddr = safemalloc((MEM_SIZE)(strlen(str)+1));
- X
- X strcpy(newaddr,str);
- X return newaddr;
- X}
- X
- Xint
- Xmakedir(dirname,nametype)
- Xregister char *dirname;
- Xint nametype;
- X{
- X#ifdef MAKEDIR
- X register char *end;
- X register char *s;
- X char tmpbuf[1024];
- X register char *tbptr = tmpbuf+5;
- X
- X for (end = dirname; *end; end++) ; /* find the end */
- X if (nametype == MD_FILE) { /* not to create last component? */
- X for (--end; end != dirname && *end != '/'; --end) ;
- X if (*end != '/')
- X return 0; /* nothing to make */
- X *end = '\0'; /* isolate file name */
- X }
- X strcpy(tmpbuf,"mkdir");
- X
- X s = end;
- X for (;;) {
- X if (stat(dirname,&filestat) >= 0 && (filestat.st_mode & S_IFDIR)) {
- X /* does this much exist as a dir? */
- X *s = '/'; /* mark this as existing */
- X break;
- X }
- X s = rindex(dirname,'/'); /* shorten name */
- X if (!s) /* relative path! */
- X break; /* hope they know what they are doing */
- X *s = '\0'; /* mark as not existing */
- X }
- X
- X for (s=dirname; s <= end; s++) { /* this is grody but efficient */
- X if (!*s) { /* something to make? */
- X sprintf(tbptr," %s",dirname);
- X tbptr += strlen(tbptr); /* make it, sort of */
- X *s = '/'; /* mark it made */
- X }
- X }
- X if (nametype == MD_DIR) /* don't need final slash unless */
- X *end = '\0'; /* a filename follows the dir name */
- X
- X return (tbptr==tmpbuf+5 ? 0 : doshell(sh,tmpbuf));
- X /* exercise our faith */
- X#else
- X sprintf(cmd_buf,"%s %s %d", filexp(DIRMAKER), dirname, nametype);
- X return doshell(sh,cmd_buf);
- X#endif
- X}
- X
- X#ifdef SETENV
- Xstatic bool firstsetenv = TRUE;
- Xextern char **environ;
- X
- Xvoid
- Xsetenv(nam,val)
- Xchar *nam, *val;
- X{
- X register int i=envix(nam); /* where does it go? */
- X
- X if (!environ[i]) { /* does not exist yet */
- X if (firstsetenv) { /* need we copy environment? */
- X int j;
- X#ifndef lint
- X char **tmpenv = (char**) /* point our wand at memory */
- X safemalloc((MEM_SIZE) (i+2) * sizeof(char*));
- X#else
- X char **tmpenv = Null(char **);
- X#endif /* lint */
- X
- X firstsetenv = FALSE;
- X for (j=0; j<i; j++) /* copy environment */
- X tmpenv[j] = environ[j];
- X environ = tmpenv; /* tell exec where it is now */
- X }
- X#ifndef lint
- X else
- X environ = (char**) saferealloc((char*) environ,
- X (MEM_SIZE) (i+2) * sizeof(char*));
- X /* just expand it a bit */
- X#endif /* lint */
- X environ[i+1] = Nullch; /* make sure it's null terminated */
- X }
- X environ[i] = safemalloc((MEM_SIZE) strlen(nam) + strlen(val) + 2);
- X /* this may or may not be in */
- X /* the old environ structure */
- X sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
- X}
- X
- Xint
- Xenvix(nam)
- Xchar *nam;
- X{
- X register int i, len = strlen(nam);
- X
- X for (i = 0; environ[i]; i++) {
- X if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
- X break; /* strnEQ must come first to avoid */
- X } /* potential SEGV's */
- X return i;
- X}
- X#endif
- X
- Xvoid
- Xnotincl(feature)
- Xchar *feature;
- X{
- X printf("\nNo room for feature \"%s\" on this machine.\n",feature) FLUSH;
- X}
- X
- Xchar *
- Xgetval(nam,def)
- Xchar *nam,*def;
- X{
- X char *val;
- X
- X if ((val = getenv(nam)) == Nullch || !*val)
- X val = def;
- X return val;
- X}
- X
- X/* grow a static string to at least a certain length */
- X
- Xvoid
- Xgrowstr(strptr,curlen,newlen)
- Xchar **strptr;
- Xint *curlen;
- Xint newlen;
- X{
- X if (newlen > *curlen) { /* need more room? */
- X if (*curlen)
- X *strptr = saferealloc(*strptr,(MEM_SIZE)newlen);
- X else
- X *strptr = safemalloc((MEM_SIZE)newlen);
- X *curlen = newlen;
- X }
- X}
- X
- Xvoid
- Xsetdef(buffer,dflt)
- Xchar *buffer,*dflt;
- X{
- X#ifdef STRICTCR
- X if (*buffer == ' ')
- X#else
- X if (*buffer == ' ' || *buffer == '\n')
- X#endif
- X {
- X if (*dflt == '^' && isupper(dflt[1]))
- X *buffer = Ctl(dflt[1]);
- X else
- X *buffer = *dflt;
- X }
- X}
- END_OF_FILE
- if test 10588 -ne `wc -c <'util.c'`; then
- echo shar: \"'util.c'\" unpacked with wrong size!
- fi
- # end of 'util.c'
- fi
- echo shar: End of archive 11 \(of 14\).
- cp /dev/null ark11isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 14 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
-